home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Source Code / C / Games / NetHack 3.1.3 / source / src / mhitu.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-08-01  |  56.8 KB  |  2,265 lines  |  [TEXT/R*ch]

  1. /*    SCCS Id: @(#)mhitu.c    3.1    93/03/14    */
  2. /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
  3. /* NetHack may be freely redistributed.  See license for details. */
  4.  
  5. #include "hack.h"
  6. #include "artifact.h"
  7.  
  8. STATIC_VAR NEARDATA struct obj *otmp;
  9.  
  10. #ifdef POLYSELF
  11. STATIC_DCL void FDECL(urustm, (struct monst *, struct obj *));
  12. # ifdef OVL1
  13. static int FDECL(passiveum, (struct permonst *,struct monst *,struct attack *));
  14. # endif /* OVL1 */
  15. #endif /* POLYSELF */
  16.  
  17. #ifdef OVLB
  18. # ifdef SEDUCE
  19. static void FDECL(mayberem, (struct obj *, const char *));
  20. # endif
  21. #endif /* OVLB */
  22.  
  23. STATIC_DCL boolean FDECL(diseasemu, (struct permonst *));
  24. STATIC_DCL int FDECL(hitmu, (struct monst *,struct attack *));
  25. STATIC_DCL int FDECL(gulpmu, (struct monst *,struct attack *));
  26. STATIC_DCL int FDECL(explmu, (struct monst *,struct attack *,BOOLEAN_P));
  27. STATIC_DCL void FDECL(missmu,(struct monst *,BOOLEAN_P,struct attack *));
  28. STATIC_DCL void FDECL(mswings,(struct monst *,struct obj *));
  29. STATIC_DCL void FDECL(wildmiss,(struct monst *));
  30.  
  31. STATIC_DCL void FDECL(hurtarmor,(struct permonst *,int));
  32. STATIC_DCL void FDECL(hitmsg,(struct monst *,struct attack *));
  33.  
  34. /* See comment in mhitm.c.  If we use this a lot it probably should be */
  35. /* changed to a parameter to mhitu. */
  36. static int dieroll;
  37.  
  38. #ifdef OVL1
  39.  
  40.  
  41. STATIC_OVL void
  42. hitmsg(mtmp, mattk)
  43. register struct monst *mtmp;
  44. register struct attack *mattk;
  45. {
  46.     int compat;
  47.  
  48.     /* Note: if opposite gender, "seductively" */
  49.     /* If same gender, "engagingly" for nymph, normal msg for others */
  50.     if((compat = could_seduce(mtmp, &youmonst, mattk))
  51.             && !mtmp->mcan && !mtmp->mspec_used) {
  52.             pline("%s %s you %s.", Monnam(mtmp),
  53.             Blind ? "talks to" : "smiles at",
  54.             compat == 2 ? "engagingly" : "seductively");
  55.     } else
  56.         switch (mattk->aatyp) {
  57.         case AT_BITE:
  58.             pline("%s bites!", Monnam(mtmp));
  59.             break;
  60.         case AT_KICK:
  61. #ifdef POLYSELF
  62.             pline("%s kicks%c", Monnam(mtmp), thick_skinned(uasmon) ? '.' : '!');
  63. #else
  64.             pline("%s kicks!", Monnam(mtmp));
  65. #endif
  66.             break;
  67.         case AT_STNG:
  68.             pline("%s stings!", Monnam(mtmp));
  69.             break;
  70.         case AT_BUTT:
  71.             pline("%s butts!", Monnam(mtmp));
  72.             break;
  73.         case AT_TUCH:
  74.             pline("%s touches you!", Monnam(mtmp));
  75.             break;
  76.         case AT_TENT:
  77.             pline("%s tentacles suck you!", 
  78.                         s_suffix(Monnam(mtmp)));
  79.             break;
  80.         case AT_EXPL:
  81.             pline("%s explodes!", Monnam(mtmp));
  82.             break;
  83.         default:
  84.             pline("%s hits!", Monnam(mtmp));
  85.         }
  86. }
  87.  
  88. STATIC_OVL void
  89. missmu(mtmp, nearmiss, mattk)        /* monster missed you */
  90. register struct monst *mtmp;
  91. register boolean nearmiss;
  92. register struct attack *mattk;
  93. {
  94.     if(could_seduce(mtmp, &youmonst, mattk) && !mtmp->mcan)
  95.         pline("%s pretends to be friendly.", Monnam(mtmp));
  96.     else {
  97.         if (!flags.verbose || !nearmiss)
  98.         pline("%s misses.", Monnam(mtmp));
  99.         else
  100.         pline("%s just misses!", Monnam(mtmp));
  101.     }
  102. }
  103.  
  104. STATIC_OVL void
  105. mswings(mtmp, otemp)        /* monster swings obj */
  106. register struct monst *mtmp;
  107. register struct obj *otemp;
  108. {
  109.     if (!flags.verbose || Blind || !mon_visible(mtmp))
  110.         return;
  111.     pline("%s %s %s %s.", Monnam(mtmp),
  112.           ((otemp->otyp >= SPEAR && otemp->otyp <= LANCE) ||
  113.            (otemp->otyp >= PARTISAN && otemp->otyp <= SPETUM) ||
  114.            otemp->otyp == TRIDENT) ? "thrusts" : "swings",
  115.           his[pronoun_gender(mtmp)], xname(otemp));
  116. }
  117.  
  118. #endif /* OVL1 */
  119. #ifdef OVLB
  120.  
  121. STATIC_OVL void
  122. wildmiss(mtmp)        /* monster attacked your displaced image */
  123.     register struct monst *mtmp;
  124. {
  125.     int compat;
  126.  
  127.     if (!flags.verbose) return;
  128.     if (!cansee(mtmp->mx, mtmp->my)) return;
  129.         /* maybe it's attacking an image around the corner? */
  130.  
  131.     compat = could_seduce(mtmp, &youmonst, (struct attack *)0);
  132.         /* we really want to have the attack here to pass --
  133.          * the previous code checked whether mtmp was a nymph,
  134.          * which was not correct either since the attack type of
  135.          * succubi/incubi varies with SEDUCE
  136.          */
  137.  
  138.     if(Invis && !perceives(mtmp->data)) {
  139.         if(compat)
  140.         pline("%s tries to touch you and misses!", Monnam(mtmp));
  141.         else
  142.         switch(rn2(3)) {
  143.         case 0: pline("%s %s wildly and misses!", Monnam(mtmp),
  144.                   nolimbs(mtmp->data) ? "lunges" : "swings");
  145.             break;
  146.         case 1: pline("%s attacks a spot beside you.", Monnam(mtmp));
  147.             break;
  148.         case 2: pline("%s strikes at %s!", Monnam(mtmp),
  149.                 Underwater ? "empty water" : "thin air");
  150.             break;
  151.         default:pline("%s %s wildly!", Monnam(mtmp),
  152.                   nolimbs(mtmp->data) ? "lunges" : "swings");
  153.             break;
  154.         }
  155.     }
  156.     else if(Displaced) {
  157.         if(compat)
  158.         pline("%s smiles %s at your %sdisplaced image...",
  159.             Monnam(mtmp),
  160.             compat == 2 ? "engagingly" : "seductively",
  161.             Invis ? "invisible " : "");
  162.         else
  163.         pline("%s strikes at your %sdisplaced image and misses you!",
  164.             /* Note: if you're both invisible and displaced,
  165.              * only monsters which see invisible will attack your
  166.              * displaced image, since the displaced image is also
  167.              * invisible.
  168.              */
  169.             Monnam(mtmp),
  170.             Invis ? "invisible " : "");
  171.     }
  172.     /* monsters may miss especially on water level where
  173.        bubbles shake the player here and there */
  174.     else if(Underwater) {
  175.         if(compat)
  176.         pline("%s reaches towards your distorted image.",Monnam(mtmp));
  177.         else
  178.         pline("%s is fooled by water reflections and misses!",Monnam(mtmp));
  179.     }
  180.     else impossible("%s attacks you without knowing your location?",
  181.         Monnam(mtmp));
  182. }
  183.  
  184. void
  185. expels(mtmp, mdat, message)
  186. register struct monst *mtmp;
  187. register struct permonst *mdat; /* if mtmp is polymorphed, mdat != mtmp->data */
  188. boolean message;
  189. {
  190.     if (message) 
  191.         if (is_animal(mdat)) 
  192.             You("get regurgitated!");
  193.         else {
  194.             char blast[40];
  195.             register int i;
  196.  
  197.             blast[0] = '\0';
  198.             for(i = 0; i < NATTK; i++)
  199.                 if(mdat->mattk[i].aatyp == AT_ENGL) 
  200.                     break;
  201.             if (mdat->mattk[i].aatyp != AT_ENGL)
  202.                   impossible("Swallower has no engulfing attack?"); 
  203.             else {
  204.                 if (is_whirly(mdat)) {
  205.                     switch (mdat->mattk[i].adtyp) {
  206.                         case AD_ELEC:
  207.                             Strcpy(blast, 
  208.                               " in a shower of sparks");
  209.                             break;
  210.                         case AD_COLD:
  211.                             Strcpy(blast, 
  212.                             " in a blast of frost");
  213.                             break;
  214.                     }
  215.                 } else
  216.                     Strcpy(blast, " with a squelch");
  217.                 You("get expelled from %s%s!", 
  218.                     mon_nam(mtmp), blast);
  219.             }
  220.         }
  221.     unstuck(mtmp);    /* ball&chain returned in unstuck() */
  222.     mnexto(mtmp);
  223.     newsym(u.ux,u.uy);
  224.     spoteffects();
  225.     /* to cover for a case where mtmp is not in a next square */
  226.     if(um_dist(mtmp->mx,mtmp->my,1))
  227.         pline("Brrooaa...  You land hard at some distance.");
  228. }
  229.  
  230. #endif /* OVLB */
  231. #ifdef OVL0
  232.  
  233. /*
  234.  * mattacku: monster attacks you
  235.  *    returns 1 if monster dies (e.g. "yellow light"), 0 otherwise
  236.  *    Note: if you're displaced or invisible the monster might attack the
  237.  *        wrong position...
  238.  *    Assumption: it's attacking you or an empty square; if there's another
  239.  *        monster which it attacks by mistake, the caller had better
  240.  *        take care of it...
  241.  */
  242. int
  243. mattacku(mtmp)
  244.     register struct monst *mtmp;
  245. {
  246.     struct    attack    *mattk;
  247.     int    i, j, tmp, sum[NATTK];
  248.     struct    permonst *mdat = mtmp->data;
  249.     boolean ranged = (distu(mtmp->mx, mtmp->my) > 3);
  250.         /* Is it near you?  Affects your actions */
  251.     boolean range2 = !monnear(mtmp, mtmp->mux, mtmp->muy);
  252.         /* Does it think it's near you?  Affects its actions */
  253.     boolean foundyou = (mtmp->mux==u.ux && mtmp->muy==u.uy);
  254.         /* Is it attacking you or your image? */
  255.     boolean youseeit = canseemon(mtmp);
  256.         /* Might be attacking your image around the corner, or
  257.          * invisible, or you might be blind....
  258.          */
  259.  
  260.     if(!ranged) nomul(0);
  261.     if(mtmp->mhp <= 0 || (Underwater && !is_swimmer(mtmp->data)))
  262.         return(0);
  263.  
  264.     /* If swallowed, can only be affected by u.ustuck */
  265.     if(u.uswallow) {
  266.         if(mtmp != u.ustuck)
  267.         return(0);
  268.         u.ustuck->mux = u.ux;
  269.         u.ustuck->muy = u.uy;
  270.         range2 = 0;
  271.         foundyou = 1;
  272.         if(u.uinvulnerable) return (0); /* stomachs can't hurt you! */
  273.         /* This is not impossible! */
  274.         /* If the swallowing monster changes into a monster
  275.          * that is not capable of swallowing you, you get
  276.          * regurgitated - dgk
  277.          *
  278.          * This code is obsolete: newcham() will handle this contingency 
  279.          * as soon as it occurs in the course of a round. - kcd
  280.          *
  281.          * for(i = 0; i < NATTK; i++)
  282.          *     if(mdat->mattk[i].aatyp == AT_ENGL) goto doattack;
  283.          *
  284.          * You("get regurgitated!");
  285.          * regurgitates(mtmp);
  286.              * return(0);
  287.          */
  288.     }
  289. /* doattack:        use commented out above */
  290. #ifdef POLYSELF
  291.     if (u.uundetected && !range2 && foundyou && !u.uswallow) {
  292.         u.uundetected = 0;
  293.         if (is_hider(uasmon)) {
  294.             coord cc; /* maybe we need a unexto() function? */
  295.  
  296.             You("fall from the ceiling!");
  297.             if (enexto(&cc, u.ux, u.uy, &playermon)) {
  298.             remove_monster(mtmp->mx, mtmp->my);
  299.             newsym(mtmp->mx,mtmp->my);
  300.             place_monster(mtmp, u.ux, u.uy);
  301.             if(mtmp->wormno) worm_move(mtmp);
  302.             teleds(cc.x, cc.y);
  303.             set_apparxy(mtmp);
  304.             newsym(u.ux,u.uy);
  305.             } else {
  306.             pline("%s is killed by a falling %s (you)!",
  307.                         Monnam(mtmp), uasmon->mname);
  308.             killed(mtmp);
  309.             newsym(u.ux,u.uy);
  310. #ifdef MUSE
  311.             if (mtmp->mhp > 0) return(0);
  312.             else
  313. #endif
  314.                 return(1);
  315.             }
  316.             if (u.usym != S_PIERCER)
  317.             return(0);    /* trappers don't attack */
  318. #ifdef MUSE
  319.             if (which_armor(mtmp, WORN_HELMET)) {
  320. #else
  321.             if (is_mercenary(mtmp->data) && m_carrying(mtmp,HELMET)) {
  322. #endif
  323.             Your("blow glances off %s helmet.", 
  324.                            s_suffix(mon_nam(mtmp)));
  325.             } else {
  326.             if (3 + find_mac(mtmp) <= rnd(20)) {
  327.                 pline("%s is hit by a falling piercer (you)!",
  328.                                 Monnam(mtmp));
  329.                 if ((mtmp->mhp -= d(3,6)) < 1)
  330.                 killed(mtmp);
  331.             } else
  332.               pline("%s is almost hit by a falling piercer (you)!",
  333.                                 Monnam(mtmp));
  334.             }
  335.         } else {
  336.             if (!youseeit)
  337.             pline("It tries to move where you are hiding.");
  338.             else {
  339.             /* Ugly kludge for eggs.  The message is phrased so as
  340.              * to be directed at the monster, not the player,
  341.              * which makes "laid by you" wrong.  For the
  342.              * parallelism to work, we can't rephrase it, so we
  343.              * zap the "laid by you" momentarily instead.
  344.              */
  345.             struct obj *obj = level.objects[u.ux][u.uy];
  346.  
  347.             if (obj) {
  348.                 int save_spe = obj->spe;
  349.                 if (obj->otyp == EGG) obj->spe = 0;
  350.          pline("Wait, %s!  There's a %s named %s hiding under %s!",
  351.                 mtmp->mnamelth ? (const char *)NAME(mtmp)
  352.                            : mtmp->data->mname,
  353.                 uasmon->mname, plname,
  354.                 doname(level.objects[u.ux][u.uy]));
  355.                 obj->spe = save_spe;
  356.             } else
  357.                 impossible("hiding under nothing?");
  358.             }
  359.             newsym(u.ux,u.uy);
  360.         }
  361.         return(0);
  362.     }
  363.     if (u.usym == S_MIMIC_DEF && !range2 && foundyou && !u.uswallow) {
  364.         if (!youseeit) pline("It gets stuck on you.");
  365.             else pline("Wait, %s!  That's a %s named %s!",
  366.             mtmp->mnamelth ? (const char *)NAME(mtmp) : mtmp->data->mname,
  367.             uasmon->mname, plname);
  368.         u.ustuck = mtmp;
  369.         u.usym = S_MIMIC;
  370.         newsym(u.ux,u.uy);
  371.         return(0);
  372.     }
  373. #endif
  374. /*    Work out the armor class differential    */
  375.     tmp = u.uac + 10;        /* tmp ~= 0 - 20 */
  376. /*    give people with Ac < -9 at least some vulnerability */
  377. /*    negative AC gives an actual AC of somewhere from -1 to the AC */
  378.     if (tmp < 10) tmp = 10 - rnd(10-tmp);
  379.     tmp += mtmp->m_lev;
  380.     if(multi < 0) tmp += 4;
  381.     if((Invis && !perceives(mdat)) || !mtmp->mcansee)
  382.         tmp -= 2;
  383.     if(mtmp->mtrapped) tmp -= 2;
  384.     if(tmp <= 0) tmp = 1;
  385.  
  386.     /* make eels visible the moment they hit/miss us */
  387.     if(mdat->mlet == S_EEL && mtmp->minvis && cansee(mtmp->mx,mtmp->my)) {
  388.         mtmp->minvis = 0;
  389.         newsym(mtmp->mx,mtmp->my);
  390.     }
  391.  
  392. /*    Special demon handling code */
  393.     if(!mtmp->cham && is_demon(mdat) && !range2
  394.        && mtmp->data != &mons[PM_BALROG]
  395.        && mtmp->data != &mons[PM_SUCCUBUS]
  396.        && mtmp->data != &mons[PM_INCUBUS])
  397.         if(!mtmp->mcan && !rn2(13))    msummon(mdat);
  398.  
  399. /*    Special lycanthrope handling code */
  400.     if(!mtmp->cham && is_were(mdat) && !range2) {
  401.  
  402.         if(is_human(mdat)) {
  403.         if(!rn2(5 - (night() * 2)) && !mtmp->mcan) new_were(mtmp);
  404.         } else if(!rn2(30) && !mtmp->mcan) new_were(mtmp);
  405.  
  406.         if(!rn2(10) && !mtmp->mcan) {
  407.         if(youseeit) {
  408.             pline("%s summons help!", Monnam(mtmp));
  409.         } else
  410.             You("feel hemmed in.");
  411.         /* Technically wrong; we really should check if you can see the
  412.          * help, but close enough...
  413.          */
  414.         if (!were_summon(mdat,FALSE) && youseeit)
  415.             pline("But none comes.");
  416.         }
  417.     }
  418.  
  419.     if(u.uinvulnerable) {
  420.         /* monster's won't attack you */
  421.         if(mtmp == u.ustuck)
  422.         pline("%s loosens its grip slightly.", Monnam(mtmp));
  423.         else if(!range2) {
  424.         if(youseeit)
  425.             pline("%s starts to attack you, but pulls back.",
  426.               Monnam(mtmp));
  427.         else
  428.             You("feel something move nearby.");
  429.         }
  430.         return (0);
  431.     }
  432.  
  433. #ifdef MUSE
  434.     /* Unlike defensive stuff, don't let them use item _and_ attack. */
  435.     /* Exception:  Medusa; her gaze is automatic.  (We actually kludge
  436.      * by permitting a full attack sequence, not just a gaze attack.)
  437.      */
  438.     if(find_offensive(mtmp)) {
  439.         int foo = use_offensive(mtmp);
  440.  
  441.         if (mtmp->data != &mons[PM_MEDUSA] && foo != 0) return(foo==1);
  442.     }
  443. #endif
  444.  
  445.     for(i = 0; i < NATTK; i++) {
  446.  
  447.         sum[i] = 0;
  448.         mattk = &(mdat->mattk[i]);
  449.         if (u.uswallow && (mattk->aatyp != AT_ENGL))
  450.         continue;
  451.         switch(mattk->aatyp) {
  452.         case AT_CLAW:    /* "hand to hand" attacks */
  453.         case AT_KICK:
  454.         case AT_BITE:
  455.         case AT_STNG:
  456.         case AT_TUCH:
  457.         case AT_BUTT:
  458.         case AT_TENT:
  459.             if(!range2) {
  460.                 if (foundyou) {
  461.                 if(tmp > (j = rnd(20+i))) {
  462. #ifdef POLYSELF
  463.                     if (mattk->aatyp != AT_KICK ||
  464.                         !thick_skinned(uasmon))
  465. #endif
  466.                     sum[i] = hitmu(mtmp, mattk);
  467.                 } else
  468.                     missmu(mtmp, (tmp == j), mattk);
  469.                 } else
  470.                 wildmiss(mtmp);
  471.             }
  472.             break;
  473.  
  474.         case AT_HUGS:    /* automatic if prev two attacks succeed */
  475.             /* Note: if displaced, prev attacks never succeeded */
  476.             if((!range2 && i>=2 && sum[i-1] && sum[i-2])
  477.                             || mtmp == u.ustuck)
  478.                 sum[i]= hitmu(mtmp, mattk);
  479.             break;
  480.  
  481.         case AT_GAZE:    /* can affect you either ranged or not */
  482.             if (youseeit)
  483.                 /* not displaced around a corner so not visible */
  484.                 sum[i] = gazemu(mtmp, mattk);
  485.             /* if gazemu returns, the player isn't dead.
  486.              * can't put this in gazemu() because youseeit might
  487.              * not be set
  488.              */
  489.             if(Reflecting && m_canseeu(mtmp) &&
  490.                !mtmp->mcan && mtmp->data == &mons[PM_MEDUSA]) {
  491.                 if(!Blind) {
  492.                 if(Reflecting & W_AMUL)
  493.                     makeknown(AMULET_OF_REFLECTION);
  494.                 else
  495.                     makeknown(SHIELD_OF_REFLECTION);
  496.                 pline("%s gaze is reflected by your %s.",
  497.                       s_suffix(Monnam(mtmp)),
  498.                       (Reflecting & W_AMUL) ?
  499.                       "medallion" : "shield");
  500.                 pline("%s is turned to stone!", Monnam(mtmp));
  501.                 }
  502.                 stoned = TRUE;
  503.                 killed(mtmp);
  504. #ifdef MUSE
  505.                 if (mtmp->mhp > 0)
  506.                 sum[i] = 0;
  507.                 else
  508. #endif
  509.                 sum[i] = 2;
  510.             }
  511.             break;
  512.  
  513.         case AT_EXPL:    /* automatic hit if next to, and aimed at you */
  514.             if(!range2) sum[i] = explmu(mtmp, mattk, foundyou);
  515.             break;
  516.  
  517.         case AT_ENGL:
  518.             if (!range2) {
  519.                 if(foundyou) {
  520.                 if(u.uswallow || tmp > (j = rnd(20+i))) {
  521.                     /* Force swallowing monster to be
  522.                      * displayed even when player is
  523.                      * moving away */
  524.                     flush_screen(1);
  525.                     sum[i] = gulpmu(mtmp, mattk);
  526.                 } else {
  527.                     missmu(mtmp, (tmp == j), mattk);
  528.                 }
  529.                            } else if (is_animal(mtmp->data))
  530.                     pline("%s gulps some air!", youseeit ?
  531.                           Monnam(mtmp) : "It");
  532.                   else
  533.                     if (youseeit)
  534.                      pline("%s lunges forward and recoils!",
  535.                            Monnam(mtmp));
  536.                     else
  537.                         You("hear a %s nearby.", 
  538.                             is_whirly(mtmp->data)? 
  539.                             "rushing noise" : 
  540.                             "splat");
  541.             }
  542.             break;
  543.         case AT_BREA:
  544.             if(range2) sum[i] = breamu(mtmp, mattk);
  545.             /* Note: breamu takes care of displacement */
  546.             break;
  547.         case AT_SPIT:
  548.             if(range2) sum[i] = spitmu(mtmp, mattk);
  549.             /* Note: spitmu takes care of displacement */
  550.             break;
  551.         case AT_WEAP:
  552.             if(range2) {
  553. #ifdef REINCARNATION
  554.                 if (!Is_rogue_level(&u.uz))
  555. #endif
  556.                     thrwmu(mtmp);
  557.             } else {
  558. #ifdef MUSE
  559.                 /* Rare but not impossible.  Normally the monster
  560.                  * wields when 2 spaces away, but it can be
  561.                  * teleported or whatever....
  562.                  */
  563.                 if (mtmp->weapon_check == NEED_WEAPON || !MON_WEP(mtmp)) {
  564.                 mtmp->weapon_check = NEED_HTH_WEAPON;
  565.                 /* mon_wield_item resets weapon_check as appropriate */
  566.                 if (mon_wield_item(mtmp) != 0) break;
  567.                 }
  568. #endif
  569.                 if (foundyou) {
  570.                 set_uasmon();
  571. #ifdef MUSE
  572.                 remove_cadavers(&mtmp->minvent);
  573.                 possibly_unwield(mtmp);
  574.                 otmp = MON_WEP(mtmp);
  575. #else
  576.                 otmp = select_hwep(mtmp);
  577. #endif
  578.                 if(otmp) {
  579.                     tmp += hitval(otmp, uasmon);
  580.                     mswings(mtmp, otmp);
  581.                 }
  582.                 if(tmp > (j = dieroll = rnd(20+i)))
  583.                     sum[i] = hitmu(mtmp, mattk);
  584.                 else
  585.                     missmu(mtmp, (tmp == j), mattk);
  586.                 } else
  587.                 wildmiss(mtmp);
  588.             }
  589.             break;
  590.         case AT_MAGC:
  591.             if (range2)
  592.                 sum[i] = buzzmu(mtmp, mattk);
  593.             else
  594.                 if (foundyou)
  595.                 sum[i] = castmu(mtmp, mattk);
  596.                 else
  597.                 pline("%s casts a spell at thin air!",
  598.                     youseeit ? Monnam(mtmp) : "It");
  599.                 /* Not totally right since castmu allows other
  600.                  * spells, such as the monster healing itself,
  601.                  * that should work even when not next to you--
  602.                  * but the previous code was just as wrong.
  603.                  * --KAA
  604.                  */
  605.             break;
  606.  
  607.         default:        /* no attack */
  608.             break;
  609.         }
  610.         if(flags.botl) bot();
  611.     /* give player a chance of waking up before dying -kaa */
  612.         if(sum[i] == 1) {        /* successful attack */
  613.         if (u.usleep && !rn2(10)) {
  614.             multi = -1;
  615.             nomovemsg = "The combat suddenly awakens you.";
  616.         }
  617.         }
  618.         if(sum[i] == 2)  return(1);     /* attacker dead */
  619.         if(sum[i] == 3) break;  /* attacker teleported, no more attacks */
  620.         /* sum[i] == 0: unsuccessful attack */
  621.     }
  622.     return(0);
  623. }
  624.  
  625. #endif /* OVL0 */
  626. #ifdef OVLB
  627.  
  628. /*
  629.  * helper function for some compilers that have trouble with hitmu
  630.  */
  631.  
  632. STATIC_OVL void
  633. hurtarmor(mdat, attk)
  634. struct permonst *mdat;
  635. int attk;
  636. {
  637.     boolean getbronze, rusting;
  638.     int    hurt;
  639.  
  640.     rusting = (attk == AD_RUST);
  641.     if (rusting) {
  642.         hurt = 1;
  643.         getbronze = (mdat == &mons[PM_BLACK_PUDDING] &&
  644.                  uarm && is_corrodeable(uarm));
  645.     }
  646.     else {
  647.         hurt=2;
  648.         getbronze = FALSE;
  649.     }
  650.     /* What the following code does: it keeps looping until it
  651.      * finds a target for the rust monster.
  652.      * Head, feet, etc... not covered by metal, or covered by
  653.      * rusty metal, are not targets.  However, your body always
  654.      * is, no matter what covers it.
  655.      */
  656.     while (1) {
  657.         switch(rn2(5)) {
  658.         case 0:
  659.         if (!rust_dmg(uarmh, rusting ? "helmet" : "leather helmet",
  660.                      hurt, FALSE))
  661.             continue;
  662.         break;
  663.         case 1:
  664.         if (uarmc) {
  665.             if (!rusting)
  666.             (void)rust_dmg(uarmc, "cloak", hurt, TRUE);
  667.             break;
  668.         }
  669.         /* Note the difference between break and continue;
  670.          * break means it was hit and didn't rust; continue
  671.          * means it wasn't a target and though it didn't rust
  672.          * something else did.
  673.          */
  674.         if (getbronze)
  675.             (void)rust_dmg(uarm, "bronze armor", 3, TRUE);
  676.         else if (uarm)
  677.             (void)rust_dmg(uarm, xname(uarm), hurt, TRUE);
  678.         break;
  679.         case 2:
  680.         if (!rust_dmg(uarms, rusting ? "shield" : "wooden shield",
  681.                      hurt, FALSE))
  682.             continue;
  683.         break;
  684.         case 3:
  685.         if (!rust_dmg(uarmg, rusting ? "metal gauntlets" : "gloves",
  686.                      hurt, FALSE))
  687.             continue;
  688.         break;
  689.         case 4:
  690.         if (!rust_dmg(uarmf, rusting ? "metal boots" : "boots",
  691.                      hurt, FALSE))
  692.             continue;
  693.         break;
  694.         }
  695.         break; /* Out of while loop */
  696.     }
  697. }
  698.  
  699. #endif /* OVLB */
  700. #ifdef OVL1
  701.  
  702. STATIC_OVL boolean
  703. diseasemu(mdat)
  704. struct permonst *mdat;
  705. {
  706.     if (defends(AD_DISE,uwep)
  707. #ifdef POLYSELF
  708.             || u.usym == S_FUNGUS
  709. #endif
  710.                         ) {
  711.         You("feel a slight illness.");
  712.         return FALSE;
  713.     } else {
  714.         if (!Sick) You("feel very sick.");
  715.         exercise(A_CON, FALSE);
  716.         make_sick(Sick ? Sick/4 + 1L : (long)rn1(ACURR(A_CON), 20), FALSE);
  717.         u.usick_cause = mdat->mname;
  718.         return TRUE;
  719.     }
  720. }
  721.  
  722. /*
  723.  * hitmu: monster hits you
  724.  *      returns 2 if monster dies (e.g. "yellow light"), 1 otherwise
  725.  *      3 if the monster lives but teleported/paralyzed, so it can't keep
  726.  *           attacking you
  727.  */
  728. STATIC_OVL int
  729. hitmu(mtmp, mattk)
  730.     register struct monst *mtmp;
  731.     register struct attack  *mattk;
  732. {
  733.     register struct permonst *mdat = mtmp->data;
  734.     register int ctmp, ptmp;
  735.     int dmg, armpro;
  736.     char     buf[BUFSZ];
  737. #ifdef POLYSELF
  738.     struct permonst *olduasmon = uasmon;
  739.     int res;
  740. #endif
  741.  
  742. /*    If the monster is undetected & hits you.  You should know where
  743.  *    the attack came from.
  744.  */
  745.     if(mtmp->mundetected && hides_under(mdat)) {
  746.         mtmp->mundetected = 0;
  747.         if(!(Blind ? Telepat : (HTelepat & (WORN_HELMET|WORN_AMUL)))) {
  748.         register struct obj *obj;
  749.  
  750.         if(OBJ_AT(mtmp->mx, mtmp->my)) {
  751.             if((obj = level.objects[mtmp->mx][mtmp->my]) != 0)
  752.             pline("%s was hidden under %s!",
  753.                   Amonnam(mtmp), doname(obj));
  754.         }
  755.         newsym(mtmp->mx, mtmp->my);
  756.         }
  757.     }
  758.  
  759. /*    First determine the base damage done */
  760.     dmg = d((int)mattk->damn, (int)mattk->damd);
  761.     if(is_undead(mdat) && midnight())
  762.         dmg += d((int)mattk->damn, (int)mattk->damd); /* extra damage */
  763.  
  764. /*    Next a cancellation factor    */
  765. /*    Use ctmp when the cancellation factor takes into account certain
  766.  *    armor's special magic protection.  Otherwise just use !mtmp->mcan.
  767.  */
  768.     armpro = 0;
  769.     if (uarm && armpro < objects[uarm->otyp].a_can)
  770.         armpro = objects[uarm->otyp].a_can;
  771.     if (uarmc && armpro < objects[uarmc->otyp].a_can)
  772.         armpro = objects[uarmc->otyp].a_can;
  773.     ctmp = !mtmp->mcan && ((rn2(3) >= armpro) || !rn2(50));
  774.  
  775. /*    Now, adjust damages via resistances or specific attacks */
  776.     switch(mattk->adtyp) {
  777.         case AD_PHYS:
  778.         if(mattk->aatyp == AT_HUGS
  779. #ifdef POLYSELF
  780.                        && !sticks(uasmon)
  781. #endif
  782.                                 ) {
  783.             if(!u.ustuck && rn2(2)) {
  784.             register struct obj *obj = (uarmc ? uarmc : uarm);
  785.  
  786.             /* if your cloak/armor is greased, monster slips off */
  787.             if (obj && obj->greased) {
  788.                 dmg = 0;
  789.                 pline("%s grabs you, but cannot hold onto your greased %s!",
  790.                   Monnam(mtmp), xname(obj));
  791.                 if (!rn2(2)) {
  792.                 pline("The grease wears off.");
  793.                 obj->greased = 0;
  794.                 }
  795.             } else {
  796.                 u.ustuck = mtmp;
  797.                 pline("%s grabs you!", Monnam(mtmp));
  798.             }
  799.             } else if(u.ustuck == mtmp) {
  800.                 exercise(A_STR, FALSE);
  801.             You("are being %s.",
  802.                   (mtmp->data == &mons[PM_ROPE_GOLEM])
  803.                   ? "choked" : "crushed");
  804.             }
  805.         } else {              /* hand to hand weapon */
  806.             if(mattk->aatyp == AT_WEAP && otmp) {
  807. #ifdef MUSE
  808.             if (otmp->otyp == CORPSE
  809.                 && otmp->corpsenm == PM_COCKATRICE) {
  810.                 dmg = 1;
  811.                 pline("%s hits you with the cockatrice corpse.",
  812.                 Monnam(mtmp));
  813.                 if (!Stoned)
  814.                     goto do_stone;
  815.             }
  816. #endif
  817.             dmg += dmgval(otmp, uasmon);
  818.             if (dmg <= 0) dmg = 1;
  819.             if (!(otmp->oartifact &&
  820.                 artifact_hit(mtmp, &youmonst, otmp, &dmg,dieroll)))
  821.                  hitmsg(mtmp, mattk);
  822. #ifdef POLYSELF
  823.             if (!dmg) break;
  824.             if (u.mh > 1 && u.mh > ((u.uac>0) ? dmg : dmg+u.uac) &&
  825.                     (u.umonnum==PM_BLACK_PUDDING
  826.                     || u.umonnum==PM_BROWN_PUDDING)) {
  827.                 /* This redundancy necessary because you have to
  828.                  * take the damage _before_ being cloned.
  829.                  */
  830.                 if (u.uac < 0) dmg += u.uac;
  831.                 if (dmg < 1) dmg = 1;
  832.                 if (dmg > 1) exercise(A_STR, FALSE);
  833.                 u.mh -= dmg;
  834.                 flags.botl = 1;
  835.                 dmg = 0;
  836.                 if(cloneu())
  837.                 You("divide as %s hits you!",mon_nam(mtmp));
  838.             }
  839.             urustm(mtmp, otmp);
  840. #endif
  841.             } else
  842.             hitmsg(mtmp, mattk);
  843.         }
  844.         break;
  845.         case AD_DISE:
  846.         hitmsg(mtmp, mattk);
  847.         if (!diseasemu(mdat)) dmg = 0;
  848.         break;
  849.         case AD_FIRE:
  850.         hitmsg(mtmp, mattk);
  851.         if(ctmp) {
  852.             pline("You're on fire!");
  853.             if (Fire_resistance) {
  854.             pline("The fire doesn't feel hot!");
  855.             dmg = 0;
  856.             }
  857.             if((int) mtmp->m_lev > rn2(20))
  858.             destroy_item(SCROLL_CLASS, AD_FIRE);
  859.             if((int) mtmp->m_lev > rn2(20))
  860.             destroy_item(POTION_CLASS, AD_FIRE);
  861.             if((int) mtmp->m_lev > rn2(25))
  862.             destroy_item(SPBOOK_CLASS, AD_FIRE);
  863.         } else dmg = 0;
  864.         break;
  865.         case AD_COLD:
  866.         hitmsg(mtmp, mattk);
  867.         if(ctmp) {
  868.             pline("You're covered in frost!");
  869.             if (Cold_resistance) {
  870.             pline("The frost doesn't seem cold!");
  871.             dmg = 0;
  872.             }
  873.             if((int) mtmp->m_lev > rn2(20))
  874.             destroy_item(POTION_CLASS, AD_COLD);
  875.         } else dmg = 0;
  876.         break;
  877.         case AD_ELEC:
  878.         hitmsg(mtmp, mattk);
  879.         if(ctmp) {
  880.             You("get zapped!");
  881.             if (Shock_resistance) {
  882.             pline("The zap doesn't shock you!");
  883.             dmg = 0;
  884.             }
  885.             if((int) mtmp->m_lev > rn2(20))
  886.             destroy_item(WAND_CLASS, AD_ELEC);
  887.             if((int) mtmp->m_lev > rn2(20))
  888.             destroy_item(RING_CLASS, AD_ELEC);
  889.         } else dmg = 0;
  890.         break;
  891.         case AD_SLEE:
  892.         hitmsg(mtmp, mattk);
  893.         if(ctmp && multi >= 0 && !rn2(5)) {
  894.             if (Sleep_resistance) break;
  895.             nomul(-rnd(10));
  896.             u.usleep = 1;
  897.             nomovemsg = "You wake up.";
  898.             if (Blind)    You("are put to sleep!");
  899.             else    You("are put to sleep by %s!",mon_nam(mtmp));
  900.         }
  901.         break;
  902.         case AD_DRST:
  903.         ptmp = A_STR;
  904.         goto dopois;
  905.         case AD_DRDX:
  906.         ptmp = A_DEX;
  907.         goto dopois;
  908.         case AD_DRCO:
  909.         ptmp = A_CON;
  910. dopois:
  911.         hitmsg(mtmp, mattk);
  912.         if(ctmp && !rn2(8)) {
  913.             Sprintf(buf, "%s %s",
  914.                 !(canseemon(mtmp) || sensemon(mtmp)) ? "Its" :
  915.                 Hallucination ? s_suffix(rndmonnam()) : 
  916.                                 s_suffix(mdat->mname),
  917.                 (mattk->aatyp == AT_BITE) ? "bite" : "sting");
  918.             poisoned(buf, ptmp, mdat->mname, 30);
  919.         }
  920.         break;
  921.         case AD_DRIN:
  922.         hitmsg(mtmp, mattk);
  923.         if (defends(AD_DRIN, uwep)
  924. #ifdef POLYSELF
  925.                     || !has_head(uasmon)
  926. #endif
  927.                                 ) {
  928.             You("don't seem harmed.");
  929.             break;
  930.         }
  931.         if (uarmh && rn2(8)) {
  932.             Your("helmet blocks the attack to your head.");
  933.             break;
  934.         }
  935.         if (Half_physical_damage) dmg = (dmg+1) / 2;
  936.         losehp(dmg, mon_nam(mtmp), KILLED_BY_AN);
  937.         Your("brain is eaten!");
  938.         /* No such thing as mindless players... */
  939.         if (ABASE(A_INT) <= ATTRMIN(A_INT)) {
  940.             int lifesaved = 0;
  941.             while(1) {
  942.             if (lifesaved)
  943.                 pline("Unfortunately your brain is still gone.");
  944.             else
  945.                 Your("last thought fades away.");
  946.             killer = "brainlessness";
  947.             killer_format = KILLED_BY;
  948.             done(DIED);
  949.             lifesaved = 1;
  950. #ifdef WIZARD
  951.             if (wizard) break;
  952. #endif
  953.             }
  954.         }
  955.         (void) adjattrib(A_INT, -rnd(2), FALSE);
  956.         exercise(A_WIS, FALSE);
  957.         break;
  958.         case AD_PLYS:
  959.         hitmsg(mtmp, mattk);
  960.         if(ctmp && multi >= 0 && !rn2(3)) {
  961.             if (Blind)    You("are frozen!");
  962.             else    You("are frozen by %s!", mon_nam(mtmp));
  963.             nomul(-rnd(10));
  964.             exercise(A_DEX, FALSE);
  965.         }
  966.         break;
  967.         case AD_DRLI:
  968.         hitmsg(mtmp, mattk);
  969.         if (ctmp && !rn2(3)
  970. #ifdef POLYSELF
  971.             && !resists_drli(uasmon)
  972. #endif
  973.             && !defends(AD_DRLI, uwep)
  974.             ) losexp();
  975.         break;
  976.         case AD_LEGS:
  977.         { register long side = rn2(2) ? RIGHT_SIDE : LEFT_SIDE;
  978.           if (mtmp->mcan) {
  979.             pline("%s nuzzles against your %s %s!", Monnam(mtmp),
  980.               (side == RIGHT_SIDE) ? "right" : "left",
  981.               body_part(LEG));
  982.           } else {
  983.             if (uarmf) {
  984.             pline("%s scratches your %s boot!", Monnam(mtmp),
  985.                 (side == RIGHT_SIDE) ? "right" : "left");
  986.             break;
  987.             }
  988.             pline("%s pricks your %s %s!", Monnam(mtmp),
  989.               (side == RIGHT_SIDE) ? "right" : "left",
  990.               body_part(LEG));
  991.             set_wounded_legs(side, rnd(60-ACURR(A_DEX)));
  992.             exercise(A_STR, FALSE);
  993.             exercise(A_DEX, FALSE);
  994.           }
  995.           break;
  996.         }
  997.         case AD_STON:    /* at present only a cockatrice */
  998.         hitmsg(mtmp, mattk);
  999.         if(!rn2(3) && !Stoned) {
  1000.             if (mtmp->mcan) {
  1001.             if (flags.soundok)
  1002.                 You("hear a cough from %s!", mon_nam(mtmp));
  1003.             } else {
  1004.             if (flags.soundok)
  1005.                 You("hear %s hissing!", s_suffix(mon_nam(mtmp)));
  1006. #ifdef MUSE
  1007. do_stone:
  1008. #endif
  1009.             if((!rn2(10) ||
  1010.                 (flags.moonphase == NEW_MOON && !have_lizard()))
  1011. #ifdef POLYSELF
  1012.                 && !resists_ston(uasmon)
  1013.                 && !(poly_when_stoned(uasmon) &&
  1014.                  polymon(PM_STONE_GOLEM))
  1015. #endif
  1016.                 ) {
  1017.                 Stoned = 5;
  1018.                 return(1);
  1019.                 /* You("turn to stone..."); */
  1020.                 /* done_in_by(mtmp); */
  1021.             }
  1022.             }
  1023.         }
  1024.         break;
  1025.         case AD_STCK:
  1026.         hitmsg(mtmp, mattk);
  1027.         if(ctmp && !u.ustuck
  1028. #ifdef POLYSELF
  1029.                      && !sticks(uasmon)
  1030. #endif
  1031.                             ) u.ustuck = mtmp;
  1032.         break;
  1033.         case AD_WRAP:
  1034.         if((!mtmp->mcan || (u.ustuck == mtmp))
  1035. #ifdef POLYSELF
  1036.             && !sticks(uasmon)
  1037. #endif
  1038.                       ) {
  1039.             if(!u.ustuck && !rn2(10)) {
  1040.             register struct obj *obj = (uarmc ? uarmc : uarm);
  1041.  
  1042.             /* if your cloak/armor is greased, monster slips off */
  1043.             if (obj && obj->greased) {
  1044.                 dmg = 0;
  1045.                 pline("%s slips off of your greased %s!",
  1046.                   Monnam(mtmp), xname(obj));
  1047.                 if (!rn2(2)) {
  1048.                 pline("The grease wears off.");
  1049.                 obj->greased = 0;
  1050.                 }
  1051.             } else {
  1052.                 pline("%s swings itself around you!",
  1053.                   Monnam(mtmp));
  1054.                 u.ustuck = mtmp;
  1055.             }
  1056.             } else if(u.ustuck == mtmp) {
  1057.             if (is_pool(mtmp->mx,mtmp->my)
  1058. #ifdef POLYSELF
  1059.                 && !is_swimmer(uasmon)
  1060. #endif
  1061.                 && !Amphibious
  1062.                ) {
  1063.                 boolean moat = (levl[u.ux][u.uy].typ != POOL) &&
  1064.                 (levl[u.ux][u.uy].typ != WATER) &&
  1065.                 !Is_medusa_level(&u.uz) &&
  1066.                 !Is_waterlevel(&u.uz);
  1067.  
  1068.                 pline("%s drowns you...", Monnam(mtmp));
  1069.                 killer_format = KILLED_BY_AN;
  1070.                 Sprintf(buf, "%s by %s",
  1071.                     moat ? "moat" : "pool of water",
  1072.                     a_monnam(mtmp));
  1073.                 killer = buf;
  1074.                 done(DROWNING);
  1075.             } else if(mattk->aatyp == AT_HUGS)
  1076.                 You("are being crushed.");
  1077.             } else {
  1078.             dmg = 0;
  1079.             if(flags.verbose)
  1080.                 pline("%s brushes against your %s.", Monnam(mtmp),
  1081.                    body_part(LEG));
  1082.             }
  1083.         } else dmg = 0;
  1084.         break;
  1085.         case AD_WERE:
  1086.         hitmsg(mtmp, mattk);
  1087. #ifdef POLYSELF
  1088.         if (ctmp && !rn2(4) && u.ulycn == -1
  1089.             && !Protection_from_shape_changers
  1090.             && !defends(AD_WERE,uwep)) {
  1091.             You("feel feverish.");
  1092.             exercise(A_CON, FALSE);
  1093.             u.ulycn = monsndx(mdat);
  1094.         }
  1095. #endif
  1096.         break;
  1097.         case AD_SGLD:
  1098.         hitmsg(mtmp, mattk);
  1099. #ifdef POLYSELF
  1100.         if (u.usym == mdat->mlet) break;
  1101. #endif
  1102.         if(!mtmp->mcan) stealgold(mtmp);
  1103.         break;
  1104.  
  1105.         case AD_SITM:    /* for now these are the same */
  1106.         case AD_SEDU:
  1107. #ifdef POLYSELF
  1108.         if (dmgtype(uasmon, AD_SEDU)
  1109. #  ifdef SEDUCE
  1110.             || dmgtype(uasmon, AD_SSEX)
  1111. #  endif
  1112.                         ) {
  1113.             if (mtmp->minvent)
  1114.     pline("%s brags about the goods some dungeon explorer provided.",
  1115.     Monnam(mtmp));
  1116.             else
  1117.     pline("%s makes some remarks about how difficult theft is lately.",
  1118.     Monnam(mtmp));
  1119.             if (!tele_restrict(mtmp)) rloc(mtmp);
  1120.             return 3;
  1121.         } else
  1122. #endif
  1123.         if(mtmp->mcan) {
  1124.             if (!Blind) {
  1125.             pline("%s tries to %s you, but you seem %s.",
  1126.                 Adjmonnam(mtmp, "plain"),
  1127.                 flags.female ? "charm" : "seduce",
  1128.                 flags.female ? "unaffected" : "uninterested");
  1129.             }
  1130.             if(rn2(3)) {
  1131.             if (!tele_restrict(mtmp)) rloc(mtmp);
  1132.             return 3;
  1133.             }
  1134.         } else {
  1135.             switch (steal(mtmp)) {
  1136.               case -1:
  1137.             return 2;
  1138.               case 0:
  1139.             break;
  1140.               default:
  1141.             if (!tele_restrict(mtmp)) rloc(mtmp);
  1142.             mtmp->mflee = 1;
  1143.             return 3;
  1144.             }
  1145.         }
  1146.         break;
  1147. #ifdef SEDUCE
  1148.         case AD_SSEX:
  1149.         if(could_seduce(mtmp, &youmonst, mattk) == 1
  1150.             && !mtmp->mcan)
  1151.             if (doseduce(mtmp))
  1152.             return 3;
  1153.         break;
  1154. #endif
  1155.         case AD_SAMU:
  1156.         hitmsg(mtmp, mattk);
  1157.         /* when the Wiz hits, 1/20 steals the amulet */
  1158.         if ( u.uhave.amulet ||
  1159.              u.uhave.bell || u.uhave.book || u.uhave.menorah
  1160. #ifdef MULDGN
  1161.              || u.uhave.questart /* carrying the Quest Artifact */
  1162. #endif
  1163.            )
  1164.             if (!rn2(20)) stealamulet(mtmp);
  1165.         break;
  1166.  
  1167.         case AD_TLPT:
  1168.         hitmsg(mtmp, mattk);
  1169.         if(ctmp) {
  1170.             if(flags.verbose)
  1171.             Your("position suddenly seems very uncertain!");
  1172.             tele();
  1173.         }
  1174.         break;
  1175.         case AD_RUST:
  1176.         hitmsg(mtmp, mattk);
  1177.         if (mtmp->mcan) break;
  1178. #if defined(POLYSELF)
  1179.         if (u.umonnum == PM_IRON_GOLEM) {
  1180.             You("rust!");
  1181.             rehumanize();
  1182.             break;
  1183.         }
  1184. #endif
  1185.         hurtarmor(mdat, AD_RUST);
  1186.         break;
  1187.         case AD_DCAY:
  1188.         hitmsg(mtmp, mattk);
  1189.         if (mtmp->mcan) break;
  1190. #if defined(POLYSELF)
  1191.         if (u.umonnum == PM_WOOD_GOLEM ||
  1192.             u.umonnum == PM_LEATHER_GOLEM) {
  1193.             You("rot!");
  1194.             rehumanize();
  1195.             break;
  1196.         }
  1197. #endif
  1198.         hurtarmor(mdat, AD_DCAY);
  1199.         break;
  1200.         case AD_HEAL:
  1201.         if(!uwep
  1202. #ifdef TOURIST
  1203.            && !uarmu
  1204. #endif
  1205.            && !uarm && !uarmh && !uarms && !uarmg && !uarmc && !uarmf) {
  1206.             pline("%s hits!  (I hope you don't mind.)", Monnam(mtmp));
  1207. #ifdef POLYSELF
  1208.             if (u.mtimedone) {
  1209.                 u.mh += rnd(7);
  1210.                 if(!rn2(7)) u.mhmax++;
  1211.                 if(u.mh > u.mhmax) u.mh = u.mhmax;
  1212.                 if(u.mh == u.mhmax && !rn2(50)) mongone(mtmp);
  1213.             } else {
  1214. #endif
  1215.                 u.uhp += rnd(7);
  1216.                 if(!rn2(7)) u.uhpmax++;
  1217.                 if(u.uhp > u.uhpmax) u.uhp = u.uhpmax;
  1218.                 if(u.uhp == u.uhpmax && !rn2(50)) mongone(mtmp);
  1219. #ifdef POLYSELF
  1220.             }
  1221. #endif
  1222.                 exercise(A_STR, TRUE);
  1223.                 exercise(A_CON, TRUE);
  1224.             if (Sick) make_sick(0L, FALSE);
  1225.             flags.botl = 1;
  1226.             if (mtmp->mhp == 0)
  1227.                 return 2; /* mongone() was called above */
  1228.             if(!rn2(50)) {
  1229.                 if (!tele_restrict(mtmp)) rloc(mtmp);
  1230.                 return 3;
  1231.             }
  1232.             dmg = 0;
  1233.         } else
  1234.             if(pl_character[0] == 'H') {
  1235.                 if (flags.soundok && !(moves % 5))
  1236.                 verbalize("Doc, I can't help you unless you cooperate.");
  1237.                 dmg = 0;
  1238.             } else hitmsg(mtmp, mattk);
  1239.         break;
  1240.         case AD_CURS:
  1241.         hitmsg(mtmp, mattk);
  1242.         if(!night() && mdat == &mons[PM_GREMLIN]) break;
  1243.         if(!mtmp->mcan && !rn2(10)) {
  1244.             if (flags.soundok)
  1245.             if (Blind) You("hear laughter.");
  1246.             else       pline("%s chuckles.", Monnam(mtmp));
  1247. #ifdef POLYSELF
  1248.             if (u.umonnum == PM_CLAY_GOLEM) {
  1249.             pline("Some writing vanishes from your head!");
  1250.             rehumanize();
  1251.             break;
  1252.             }
  1253. #endif
  1254.             attrcurse();
  1255.         }
  1256.         break;
  1257.         case AD_STUN:
  1258.         hitmsg(mtmp, mattk);
  1259.         if(!mtmp->mcan && !rn2(4)) {
  1260.             make_stunned(HStun + dmg, TRUE);
  1261.             dmg /= 2;
  1262.         }
  1263.         break;
  1264.         case AD_ACID:
  1265.         hitmsg(mtmp, mattk);
  1266.         if(!mtmp->mcan && !rn2(3))
  1267. #ifdef POLYSELF
  1268.             if (resists_acid(uasmon)) {
  1269.             pline("You're covered in acid, but it seems harmless.");
  1270.             dmg = 0;
  1271.             } else
  1272. #endif
  1273.               {
  1274.             pline("You're covered in acid!    It burns!");
  1275.             exercise(A_STR, FALSE);
  1276.               }
  1277.         else        dmg = 0;
  1278.         break;
  1279.         case AD_SLOW:
  1280.         hitmsg(mtmp, mattk);
  1281.         if(!ctmp && (Fast & (INTRINSIC|TIMEOUT)) &&
  1282.                     !defends(AD_SLOW, uwep) && !rn2(4)) {
  1283.             Fast &= ~(INTRINSIC|TIMEOUT);
  1284.             You("feel yourself slowing down.");
  1285.             exercise(A_DEX, FALSE);
  1286.         }
  1287.         break;
  1288.         case AD_DREN:
  1289.         hitmsg(mtmp, mattk);
  1290.         if(!ctmp && !rn2(4)) drain_en(dmg);
  1291.         dmg = 0;
  1292.         break;
  1293.         case AD_CONF:
  1294.         hitmsg(mtmp, mattk);
  1295.         if(!mtmp->mcan && !rn2(4) && !mtmp->mspec_used) {
  1296.             mtmp->mspec_used = mtmp->mspec_used + (dmg + rn2(6));
  1297.             if(Confusion)
  1298.              You("are getting even more confused.");
  1299.             else You("are getting confused.");
  1300.             make_confused(HConfusion + dmg, FALSE);
  1301.         }
  1302.         /* fall through to next case */
  1303.         case AD_DETH:
  1304.         pline("%s reaches out with its deadly touch.", Monnam(mtmp));
  1305. #ifdef POLYSELF
  1306.         if (is_undead(uasmon)) {
  1307.             /* Still does normal damage */
  1308.             pline("Was that the touch of death?");
  1309.             break;
  1310.         }
  1311. #endif
  1312.         if(!Antimagic && rn2(20) > 16)  {
  1313.             killer_format = KILLED_BY_AN;
  1314.             killer = "touch of death";
  1315.             done(DIED);
  1316.         } else {
  1317.             if(!rn2(5)) {
  1318.             if(Antimagic) shieldeff(u.ux, u.uy);
  1319.             pline("Lucky for you, it didn't work!");
  1320.             dmg = 0;
  1321.             } else You("feel your life force draining away...");
  1322.         }
  1323.         break;
  1324.         case AD_PEST:
  1325.         pline("%s reaches out, and you feel fever and chills.",
  1326.             Monnam(mtmp));
  1327.         (void) diseasemu(mdat); /* plus the normal damage */
  1328.         break;
  1329.         case AD_FAMN:
  1330.         pline("%s reaches out, and your body shrivels.",
  1331.             Monnam(mtmp));
  1332.         exercise(A_CON, FALSE);
  1333.         morehungry(rn1(40,40));
  1334.         /* plus the normal damage */
  1335.         break;
  1336.         default:    dmg = 0;
  1337.             break;
  1338.     }
  1339.     if(u.uhp < 1) done_in_by(mtmp);
  1340.  
  1341. /*    Negative armor class reduces damage done instead of fully protecting
  1342.  *    against hits.
  1343.  */
  1344.     if (dmg && u.uac < 0) {
  1345.         dmg -= rnd(-u.uac);
  1346.         if (dmg < 1) dmg = 1;
  1347.     }
  1348.  
  1349.     if(dmg) {
  1350.         if(Half_physical_damage)
  1351.         dmg = (dmg+1) / 2;
  1352. #ifdef MULDGN
  1353.         else if(pl_character[0] == 'P' && uwep && is_quest_artifact(uwep)
  1354.             && is_undead(mtmp->data))
  1355.         dmg = (dmg+1) / 2;
  1356. #endif
  1357.         mdamageu(mtmp, dmg);
  1358.     }
  1359.  
  1360. #ifdef POLYSELF
  1361.     if (dmg) {
  1362.         res = passiveum(olduasmon, mtmp, mattk);
  1363.         stop_occupation();
  1364.         return res;
  1365.     } else
  1366.         return 1;
  1367. #else
  1368.     stop_occupation();
  1369.     return 1;
  1370. #endif
  1371. }
  1372.  
  1373. #endif /* OVL1 */
  1374. #ifdef OVLB
  1375.  
  1376. STATIC_OVL int
  1377. gulpmu(mtmp, mattk)    /* monster swallows you, or damage if u.uswallow */
  1378.     register struct monst *mtmp;
  1379.     register struct attack  *mattk;
  1380. {
  1381.     struct trap *t = t_at(u.ux, u.uy);
  1382.     int    tmp = d((int)mattk->damn, (int)mattk->damd);
  1383.     int    tim_tmp;
  1384.     register struct obj *otmp2;
  1385. #ifdef WALKIES
  1386.     int    i;
  1387. #endif
  1388.  
  1389.     if(!u.uswallow) {    /* swallows you */
  1390. #ifdef POLYSELF
  1391.         if (uasmon->msize >= MZ_HUGE) return(0);
  1392. #endif
  1393.         if ((t && ((t->ttyp == PIT) || (t->ttyp == SPIKED_PIT))) &&
  1394.             sobj_at(BOULDER, u.ux, u.uy))
  1395.             return(0);    
  1396.         if (Punished) unplacebc();    /* ball&chain go away */
  1397.         remove_monster(mtmp->mx, mtmp->my);
  1398.         place_monster(mtmp, u.ux, u.uy);
  1399.         u.ustuck = mtmp;
  1400.         newsym(mtmp->mx,mtmp->my);
  1401.         pline("%s engulfs you!", Monnam(mtmp));
  1402.         stop_occupation();
  1403.         if (u.utrap) {
  1404.             You("are released from the %s!",
  1405.                 u.utraptype==TT_WEB ? "web" : "trap");
  1406.             u.utrap = 0;
  1407.         }
  1408. #ifdef WALKIES
  1409.         if((i = number_leashed()) > 0) {
  1410.             pline("The leash%s snap%s loose.",
  1411.                     (i > 1) ? "es" : "",
  1412.                     (i > 1) ? "" : "s");
  1413.             unleash_all();
  1414.         }
  1415. #endif
  1416. #ifdef POLYSELF
  1417.         if (u.umonnum==PM_COCKATRICE && !resists_ston(mtmp->data)) {
  1418.             pline("%s turns to stone!", Monnam(mtmp));
  1419.             stoned = 1;
  1420.             xkilled(mtmp, 0);
  1421. # ifdef MUSE
  1422.             if (mtmp->mhp > 0) return 0;
  1423.             else
  1424. # endif
  1425.                 return 2;
  1426.         }
  1427. #endif
  1428.         display_nhwindow(WIN_MESSAGE, FALSE);
  1429.         vision_recalc(2);    /* hero can't see anything */
  1430.         u.uswallow = 1;
  1431.         /*assume that u.uswldtim always set >=0*/
  1432.         u.uswldtim = (tim_tmp =
  1433.             (-u.uac + 10 + rnd(25 - (int)mtmp->m_lev)) >> 1) > 0 ?
  1434.                 tim_tmp : 0;
  1435.         swallowed(1);
  1436.         for(otmp2 = invent; otmp2; otmp2 = otmp2->nobj) {
  1437.             (void) snuff_lit(otmp2);
  1438.         }
  1439.     } else {
  1440.  
  1441.         if(mtmp != u.ustuck) return(0);
  1442.         switch(mattk->adtyp) {
  1443.  
  1444.         case AD_DGST:
  1445.             if(u.uswldtim <= 1) {    /* a3 *//*no cf unsigned <=0*/
  1446.             pline("%s totally digests you!", Monnam(mtmp));
  1447.             tmp = u.uhp;
  1448.             if (Half_physical_damage) tmp *= 2; /* sorry */
  1449.             } else {
  1450.             pline("%s digests you!", Monnam(mtmp));
  1451.                 exercise(A_STR, FALSE);
  1452.             }
  1453.             break;
  1454.         case AD_PHYS:
  1455.             You("are pummeled with debris!");
  1456.             exercise(A_STR, FALSE);
  1457.             break;
  1458.         case AD_ACID:
  1459. #ifdef POLYSELF
  1460.             if (resists_acid(uasmon)) {
  1461.             You("are covered with a seemingly harmless goo.");
  1462.             tmp = 0;
  1463.             } else
  1464. #endif
  1465.             {
  1466.               if (Hallucination) pline("Ouch!  You've been slimed!");
  1467.               else You("are covered in slime!  It burns!");
  1468.               exercise(A_STR, FALSE);
  1469.             }
  1470.             break;
  1471.         case AD_BLND:
  1472.             if (!defends(AD_BLND, uwep)) {
  1473.             if(!Blind) {
  1474.                 You("can't see in here!");
  1475.                 make_blinded((long)tmp,FALSE);
  1476.             } else
  1477.                 /* keep him blind until disgorged */
  1478.                 make_blinded(Blinded+1,FALSE);
  1479.             }
  1480.             tmp = 0;
  1481.             break;
  1482.         case AD_ELEC:
  1483.             if(!mtmp->mcan && rn2(2)) {
  1484.             pline("The air around you crackles with electricity.");
  1485.             if (Shock_resistance) {
  1486.                 shieldeff(u.ux, u.uy);
  1487.                 You("seem unhurt.");
  1488. #if defined(POLYSELF)
  1489.                 ugolemeffects(AD_ELEC,tmp);
  1490. #endif
  1491.                 tmp = 0;
  1492.             }
  1493.             } else tmp = 0;
  1494.             break;
  1495.         case AD_COLD:
  1496.             if(!mtmp->mcan && rn2(2)) {
  1497.             if (Cold_resistance) {
  1498.                 shieldeff(u.ux, u.uy);
  1499.                 You("feel mildly chilly.");
  1500. #if defined(POLYSELF)
  1501.                 ugolemeffects(AD_COLD,tmp);
  1502. #endif
  1503.                 tmp = 0;
  1504.             } else You("are freezing to death!");
  1505.             } else tmp = 0;
  1506.             break;
  1507.         case AD_FIRE:
  1508.             if(!mtmp->mcan && rn2(2)) {
  1509.             if (Fire_resistance) {
  1510.                 shieldeff(u.ux, u.uy);
  1511.                 You("feel mildly hot.");
  1512. #if defined(POLYSELF)
  1513.                 ugolemeffects(AD_FIRE,tmp);
  1514. #endif
  1515.                 tmp = 0;
  1516.             } else You("are burning to a crisp!");
  1517.             } else tmp = 0;
  1518.             break;
  1519.         case AD_DISE:
  1520.             if (!diseasemu(mtmp->data)) tmp = 0;
  1521.             break;
  1522.         default:    tmp = 0;
  1523.                 break;
  1524.         }
  1525.     }
  1526.  
  1527.     if (Half_physical_damage) tmp = (tmp+1) / 2;
  1528.  
  1529.     mdamageu(mtmp, tmp);
  1530.     if(tmp) stop_occupation();
  1531.     if(u.uswldtim) --u.uswldtim;
  1532.     if(!u.uswldtim
  1533. #ifdef POLYSELF
  1534.         || u.umonnum==PM_COCKATRICE
  1535.         || uasmon->msize >= MZ_HUGE
  1536. #endif
  1537.         ) {
  1538. #ifdef POLYSELF
  1539.         if (u.umonnum == PM_COCKATRICE) {
  1540.         pline("%s very hurriedly %s you!", Monnam(mtmp), 
  1541.                is_animal(mtmp->data)? "regurgitates" : "expels");
  1542.         } else {
  1543. #endif
  1544.         You("get %s!", 
  1545.             is_animal(mtmp->data)? "regurgitated" : "expelled");
  1546.         if(flags.verbose && is_animal(mtmp->data))
  1547.             pline("Obviously %s doesn't like your taste.",
  1548.                    mon_nam(mtmp));
  1549. #ifdef POLYSELF
  1550.         }
  1551. #endif
  1552.         expels(mtmp, mtmp->data, FALSE);
  1553.     }
  1554.     return(1);
  1555. }
  1556.  
  1557. STATIC_OVL int
  1558. explmu(mtmp, mattk, ufound)    /* monster explodes in your face */
  1559. register struct monst *mtmp;
  1560. register struct attack  *mattk;
  1561. boolean ufound;
  1562. {
  1563.     if (mtmp->mcan) return(0);
  1564.  
  1565.     if (!ufound)
  1566.     pline("%s explodes at a spot in thin air!",
  1567.           canseemon(mtmp) ? Monnam(mtmp) : "It");
  1568.     else {
  1569.     register int tmp = d((int)mattk->damn, (int)mattk->damd);
  1570.     register boolean not_affected = defends((int)mattk->adtyp, uwep);
  1571.  
  1572.     hitmsg(mtmp, mattk);
  1573.  
  1574.     switch (mattk->adtyp) {
  1575.         case AD_COLD:
  1576.         not_affected |= Cold_resistance;
  1577.  
  1578.         if (!not_affected) {
  1579.             if (ACURR(A_DEX) > rnd(20)) {
  1580.             You("duck some of the blast.");
  1581.             tmp = (tmp+1) / 2;
  1582.             } else {
  1583.                 if (flags.verbose) You("get blasted!");
  1584.             }
  1585.             if (Half_physical_damage) tmp = (tmp+1) / 2;
  1586.             mdamageu(mtmp, tmp);
  1587.         }
  1588.         break;
  1589.  
  1590.         case AD_BLND:
  1591.         not_affected |=
  1592. #ifdef POLYSELF
  1593.             (u.umonnum == PM_YELLOW_LIGHT) ||
  1594. #endif
  1595.             Blind;
  1596.         if (!not_affected) {
  1597.             if (mon_visible(mtmp)) {
  1598.             You("are blinded by a blast of light!");
  1599.             make_blinded((long)tmp, FALSE);
  1600.             } else
  1601.             if (flags.verbose)
  1602.             You("get the impression it was not terribly bright.");
  1603.         }
  1604.         break;
  1605.  
  1606.         default:
  1607.         break;
  1608.     }
  1609.     if (not_affected) {
  1610.         You("seem unaffected by it.");
  1611. #if defined(POLYSELF)
  1612.         ugolemeffects((int)mattk->adtyp, tmp);
  1613. #endif
  1614.     }
  1615.     }
  1616.     mondead(mtmp);
  1617. #ifdef MUSE
  1618.     if (mtmp->mhp > 0) return(0);
  1619. #endif
  1620.     return(2);    /* it dies */
  1621. }
  1622.  
  1623. int
  1624. gazemu(mtmp, mattk)    /* monster gazes at you */
  1625.     register struct monst *mtmp;
  1626.     register struct attack  *mattk;
  1627. {
  1628.     switch(mattk->adtyp) {
  1629.         case AD_STON:
  1630.         if (mtmp->mcan) {
  1631.             You("notice that %s isn't all that ugly.",mon_nam(mtmp));
  1632.            break;
  1633.         }
  1634.         if (canseemon(mtmp)) {
  1635.             You("look upon %s.", mon_nam(mtmp));
  1636. # ifdef POLYSELF
  1637.             if (resists_ston(uasmon)) {
  1638.                 pline("So what?");
  1639.                 break;
  1640.             }
  1641.             if(poly_when_stoned(uasmon) && polymon(PM_STONE_GOLEM))
  1642.                 break;
  1643. # endif
  1644.             You("turn to stone...");
  1645.             killer_format = KILLED_BY_AN;
  1646.             killer = mons[PM_MEDUSA].mname;
  1647.             done(STONING);
  1648.             }
  1649.         break;
  1650.         case AD_CONF:
  1651.         if(!mtmp->mcan && canseemon(mtmp) && mtmp->mcansee && 
  1652.                     !mtmp->mspec_used && rn2(5)) {
  1653.             int conf = d(3,4);
  1654.  
  1655.             mtmp->mspec_used = mtmp->mspec_used + (conf + rn2(6));
  1656.             if(!Confusion)
  1657.             pline("%s gaze confuses you!", 
  1658.                               s_suffix(Monnam(mtmp)));
  1659.             else
  1660.             You("are getting more and more confused.");
  1661.             make_confused(HConfusion + conf, FALSE);
  1662.         }
  1663.         break;
  1664.         case AD_STUN:
  1665.         if(!mtmp->mcan && canseemon(mtmp) && mtmp->mcansee &&
  1666.                     !mtmp->mspec_used && rn2(5)) {
  1667.             int stun = d(2,6);
  1668.  
  1669.             pline("%s stares piercingly at you!", Monnam(mtmp));
  1670.             mtmp->mspec_used = mtmp->mspec_used + (stun + rn2(6));
  1671.             make_stunned(HStun + stun, TRUE);
  1672.         }
  1673.         break;
  1674.         case AD_BLND:
  1675.         if(!mtmp->mcan && canseemon(mtmp) && !defends(AD_BLND, uwep) &&
  1676.            distu(mtmp->mx,mtmp->my) <= BOLT_LIM*BOLT_LIM) {
  1677.             int blnd = d((int)mattk->damn, (int)mattk->damd);
  1678.             You("are blinded by %s radiance!", 
  1679.                           s_suffix(mon_nam(mtmp)));
  1680.             make_blinded((long)blnd,FALSE);
  1681.             make_stunned((long)d(1,3),TRUE);
  1682.         }
  1683.         break;
  1684.         default: impossible("Gaze attack %d?", mattk->adtyp);
  1685.         break;
  1686.     }
  1687.     return(1);
  1688. }
  1689.  
  1690. #endif /* OVLB */
  1691. #ifdef OVL1
  1692.  
  1693. void
  1694. mdamageu(mtmp, n)    /* mtmp hits you for n points damage */
  1695.     register struct monst *mtmp;
  1696.     register int n;
  1697. {
  1698. #ifdef POLYSELF
  1699.     if (u.mtimedone) {
  1700.         u.mh -= n;
  1701.         flags.botl = 1;
  1702.         if (u.mh < 1) rehumanize();
  1703.         return;
  1704.     }
  1705. #endif
  1706.     u.uhp -= n;
  1707.     flags.botl = 1;
  1708.     if(u.uhp < 1)
  1709.         done_in_by(mtmp);
  1710. }
  1711.  
  1712. #endif /* OVL1 */
  1713. #ifdef OVLB
  1714.  
  1715. #ifdef POLYSELF
  1716. STATIC_OVL void
  1717. urustm(mon, obj)
  1718. register struct monst *mon;
  1719. register struct obj *obj;
  1720. {
  1721.     boolean vis;
  1722.  
  1723.     if (!mon || !obj) return; /* just in case */
  1724.     vis = cansee(mon->mx, mon->my);
  1725.     if (u.umonnum == PM_RUST_MONSTER && 
  1726.         is_rustprone(obj) && obj->oeroded < MAX_ERODE) {
  1727.         if (obj->greased || obj->oerodeproof || (obj->blessed && rn2(3))) {
  1728.             if (vis)
  1729.             pline("Somehow, %s weapon is not affected.",
  1730.                         s_suffix(mon_nam(mon)));
  1731.             if (obj->greased && !rn2(2)) obj->greased = 0;
  1732.         } else {
  1733.             if (vis)
  1734.             pline("%s %s%s!",
  1735.                     s_suffix(Monnam(mon)), aobjnam(obj, "rust"),
  1736.                     obj->oeroded ? " further" : "");
  1737.             obj->oeroded++;
  1738.         }
  1739.     }
  1740. }
  1741. #endif
  1742.  
  1743. #endif /* OVLB */
  1744. #ifdef OVL1
  1745.  
  1746. int
  1747. could_seduce(magr,mdef,mattk)
  1748. struct monst *magr, *mdef;
  1749. struct attack *mattk;
  1750. /* returns 0 if seduction impossible,
  1751.  *       1 if fine,
  1752.  *       2 if wrong gender for nymph */
  1753. {
  1754.     register struct permonst *pagr;
  1755.     boolean agrinvis, defperc;
  1756.     xchar genagr, gendef;
  1757.  
  1758.     if(magr == &youmonst) {
  1759.         pagr = uasmon;
  1760.         agrinvis = (Invis != 0);
  1761.         genagr = poly_gender();
  1762.     } else {
  1763.         pagr = magr->data;
  1764.         agrinvis = magr->minvis;
  1765.         genagr = gender(magr);
  1766.     }
  1767.     if(mdef == &youmonst) {
  1768.         defperc = (See_invisible != 0);
  1769.         gendef = poly_gender();
  1770.     } else {
  1771.         defperc = perceives(mdef->data);
  1772.         gendef = gender(mdef);
  1773.     }
  1774.  
  1775.     if(agrinvis && !defperc
  1776. #ifdef SEDUCE
  1777.         && mattk && mattk->adtyp != AD_SSEX
  1778. #endif
  1779.         )
  1780.         return 0;
  1781.  
  1782.     if(pagr->mlet != S_NYMPH
  1783.         && ((pagr != &mons[PM_INCUBUS] && pagr != &mons[PM_SUCCUBUS])
  1784. #ifdef SEDUCE
  1785.             || (mattk && mattk->adtyp != AD_SSEX)
  1786. #endif
  1787.            ))
  1788.         return 0;
  1789.     
  1790.     if(genagr == 1 - gendef)
  1791.         return 1;
  1792.     else
  1793.         return (pagr->mlet == S_NYMPH) ? 2 : 0;
  1794. }
  1795.  
  1796. #endif /* OVL1 */
  1797. #ifdef OVLB
  1798.  
  1799. #ifdef SEDUCE
  1800. /* Returns 1 if monster teleported */
  1801. int
  1802. doseduce(mon)
  1803. register struct monst *mon;
  1804. {
  1805.     register struct obj *ring, *nring;
  1806.     boolean fem = (mon->data == &mons[PM_SUCCUBUS]); /* otherwise incubus */
  1807.     char qbuf[QBUFSZ];
  1808.  
  1809.     if (mon->mcan || mon->mspec_used) {
  1810.           pline("%s acts as though %s has got a %sheadache.",
  1811.               Monnam(mon), he[pronoun_gender(mon)],
  1812.               mon->mcan ? "severe " : "");
  1813.         return 0;
  1814.     }
  1815.  
  1816.     if (unconscious()) {
  1817.         pline("%s seems dismayed at your lack of response.",
  1818.               Monnam(mon));
  1819.         return 0;
  1820.     }
  1821.  
  1822.     if (Blind) pline("It caresses you...");
  1823.     else You("feel very attracted to %s.", mon_nam(mon));
  1824.  
  1825.     for(ring = invent; ring; ring = nring) {
  1826.         nring = ring->nobj;
  1827.         if (ring->otyp != RIN_ADORNMENT) continue;
  1828.         if (fem) {
  1829.         if (rn2(20) < ACURR(A_CHA)) {
  1830.             Sprintf(qbuf, "\"That %s looks pretty.  May I have it?\"",
  1831.             xname(ring));
  1832.             makeknown(RIN_ADORNMENT);
  1833.             if (yn(qbuf) == 'n') continue;
  1834.         } else pline("%s decides she'd like your %s, and takes it.",
  1835.             Blind ? "She" : Monnam(mon), xname(ring));
  1836.         makeknown(RIN_ADORNMENT);
  1837.         if (ring==uleft || ring==uright) Ring_gone(ring);
  1838.         if (ring==uwep) setuwep((struct obj *)0);
  1839.         freeinv(ring);
  1840.         mpickobj(mon,ring);
  1841.         } else {
  1842.         char buf[BUFSZ];
  1843.  
  1844.         if (uleft && uright && uleft->otyp == RIN_ADORNMENT
  1845.                 && uright->otyp==RIN_ADORNMENT)
  1846.             break;
  1847.         if (ring==uleft || ring==uright) continue;
  1848.         if (rn2(20) < ACURR(A_CHA)) {
  1849.             Sprintf(qbuf,"\"That %s looks pretty.  Would you wear it for me?\"",
  1850.             xname(ring));
  1851.             makeknown(RIN_ADORNMENT);
  1852.             if (yn(qbuf) == 'n') continue;
  1853.         } else {
  1854.             pline("%s decides you'd look prettier wearing your %s,",
  1855.             Blind ? "He" : Monnam(mon), xname(ring));
  1856.             pline("and puts it on your finger.");
  1857.         }
  1858.         makeknown(RIN_ADORNMENT);
  1859.         if (!uright) {
  1860.             pline("%s puts %s on your right hand.",
  1861.             Blind ? "He" : Monnam(mon), the(xname(ring)));
  1862.             setworn(ring, RIGHT_RING);
  1863.         } else if (!uleft) {
  1864.             pline("%s puts %s on your left hand.",
  1865.             Blind ? "He" : Monnam(mon), the(xname(ring)));
  1866.             setworn(ring, LEFT_RING);
  1867.         } else if (uright && uright->otyp != RIN_ADORNMENT) {
  1868.             Strcpy(buf, xname(uright));
  1869.             pline("%s replaces your %s with your %s.",
  1870.             Blind ? "He" : Monnam(mon), buf, xname(ring));
  1871.             Ring_gone(uright);
  1872.             setworn(ring, RIGHT_RING);
  1873.         } else if (uleft && uleft->otyp != RIN_ADORNMENT) {
  1874.             Strcpy(buf, xname(uleft));
  1875.             pline("%s replaces your %s with your %s.",
  1876.             Blind ? "He" : Monnam(mon), buf, xname(ring));
  1877.             Ring_gone(uleft);
  1878.             setworn(ring, LEFT_RING);
  1879.         } else impossible("ring replacement");
  1880.         Ring_on(ring);
  1881.             prinv(NULL, ring, 0L);
  1882.         }
  1883.     }
  1884.  
  1885.     if (!uarmc && !uarmf && !uarmg && !uarms && !uarmh
  1886. #ifdef TOURIST
  1887.                                 && !uarmu
  1888. #endif
  1889.                                     )
  1890.         pline("%s murmurs sweet nothings into your ear.",
  1891.             Blind ? (fem ? "She" : "He") : Monnam(mon));
  1892.     else
  1893.         pline("%s murmurs in your ear, while helping you undress.",
  1894.             Blind ? (fem ? "She" : "He") : Monnam(mon));
  1895.     mayberem(uarmc, "cloak");
  1896.     if(!uarmc)
  1897.         mayberem(uarm, "suit");
  1898.     mayberem(uarmf, "boots");
  1899.     if(!uwep || !welded(uwep))
  1900.         mayberem(uarmg, "gloves");
  1901.     mayberem(uarms, "shield");
  1902.     mayberem(uarmh, "helmet");
  1903. #ifdef TOURIST
  1904.     if(!uarmc && !uarm)
  1905.         mayberem(uarmu, "shirt");
  1906. #endif
  1907.  
  1908.     if (uarm || uarmc) {
  1909.         verbalize("You're such a %s; I wish...",
  1910.                 flags.female ? "sweet lady" : "nice guy");
  1911.         if (!tele_restrict(mon)) rloc(mon);
  1912.         return 1;
  1913.     }
  1914.     if (u.ualign.type == A_CHAOTIC && u.ualign.record < ALIGNLIM)
  1915.         u.ualign.record++;
  1916.  
  1917.     /* by this point you have discovered mon's identity, blind or not... */
  1918.     pline("Time stands still while you and %s lie in each other's arms...",
  1919.         mon_nam(mon));
  1920.     if (rn2(35) > ACURR(A_CHA) + ACURR(A_INT)) {
  1921.         /* Don't bother with mspec_used here... it didn't get tired! */
  1922.         pline("%s seems to have enjoyed it more than you...",
  1923.             Monnam(mon));
  1924.         switch (rn2(5)) {
  1925.             case 0: You("feel drained of energy.");
  1926.                 u.uen = 0;
  1927.                 u.uenmax -= rnd(Half_physical_damage ? 5 : 10);
  1928.                     exercise(A_CON, FALSE);
  1929.                 if (u.uenmax < 0) u.uenmax = 0;
  1930.                 break;
  1931.             case 1: You("are down in the dumps.");
  1932.                 (void) adjattrib(A_CON, -1, TRUE);
  1933.                     exercise(A_CON, FALSE);
  1934.                 flags.botl = 1;
  1935.                 break;
  1936.             case 2: Your("senses are dulled.");
  1937.                 (void) adjattrib(A_WIS, -1, TRUE);
  1938.                     exercise(A_WIS, FALSE);
  1939.                 flags.botl = 1;
  1940.                 break;
  1941.             case 3:
  1942. #ifdef POLYSELF
  1943.                 if (resists_drli(uasmon))
  1944.                     You("have a curious feeling...");
  1945.                 else {
  1946. #endif
  1947.                     You("feel out of shape.");
  1948.                     losexp();
  1949.                     if(u.uhp <= 0) {
  1950.                     killer_format = KILLED_BY;
  1951.                     killer = "overexertion";
  1952.                     done(DIED);
  1953.                     }
  1954. #ifdef POLYSELF
  1955.                 }
  1956. #endif
  1957.                 break;
  1958.             case 4: {
  1959.                 int tmp;
  1960.                 You("feel exhausted.");
  1961.                     exercise(A_STR, FALSE);
  1962.                 tmp = rn1(10, 6);
  1963.                 if(Half_physical_damage) tmp = (tmp+1) / 2;
  1964.                 losehp(tmp, "exhaustion", KILLED_BY);
  1965.                 break;
  1966.             }
  1967.         }
  1968.     } else {
  1969.         mon->mspec_used = rnd(100); /* monster is worn out */
  1970.         You("seem to have enjoyed it more than %s...", mon_nam(mon));
  1971.         switch (rn2(5)) {
  1972.             case 0: You("feel raised to your full potential.");
  1973.                     exercise(A_CON, TRUE);
  1974.                 u.uen = (u.uenmax += rnd(5));
  1975.                 break;
  1976.             case 1: You("feel good enough to do it again.");
  1977.                 (void) adjattrib(A_CON, 1, TRUE);
  1978.                     exercise(A_CON, TRUE);
  1979.                 flags.botl = 1;
  1980.                 break;
  1981.             case 2: You("will always remember %s...", mon_nam(mon));
  1982.                 (void) adjattrib(A_WIS, 1, TRUE);
  1983.                     exercise(A_WIS, TRUE);
  1984.                 flags.botl = 1;
  1985.                 break;
  1986.             case 3: pline("That was a very educational experience.");
  1987.                 pluslvl();
  1988.                     exercise(A_WIS, TRUE);
  1989.                 break;
  1990.             case 4: You("feel restored to health!");
  1991.                 u.uhp = u.uhpmax;
  1992. #ifdef POLYSELF
  1993.                 if (u.mtimedone) u.mh = u.mhmax;
  1994. #endif
  1995.                     exercise(A_STR, TRUE);
  1996.                 flags.botl = 1;
  1997.                 break;
  1998.         }
  1999.     }
  2000.  
  2001.     if (mon->mtame) /* don't charge */ ;
  2002.     else if (rn2(20) < ACURR(A_CHA)) {
  2003.         pline("%s demands that you pay %s, but you refuse...",
  2004.             Monnam(mon), him[fem]);
  2005.     }
  2006. #ifdef POLYSELF
  2007.     else if (u.umonnum == PM_LEPRECHAUN)
  2008.         pline("%s tries to take your money, but fails...",
  2009.                 Monnam(mon));
  2010. #endif
  2011.     else {
  2012.         long cost;
  2013.  
  2014.         if (u.ugold > (long)LARGEST_INT - 10L)
  2015.             cost = (long) rnd(LARGEST_INT) + 500L;
  2016.         else
  2017.             cost = (long) rnd((int)u.ugold + 10) + 500L;
  2018.         if (mon->mpeaceful) {
  2019.             cost /= 5L;
  2020.             if (!cost) cost = 1L;
  2021.         }
  2022.         if (cost > u.ugold) cost = u.ugold;
  2023.         if (!cost) verbalize("It's on the house!");
  2024.         else {
  2025.             pline("%s takes %ld zorkmid%s for services rendered!",
  2026.                 Monnam(mon), cost, plur(cost));
  2027.             u.ugold -= cost;
  2028.             mon->mgold += cost;
  2029.             flags.botl = 1;
  2030.         }
  2031.     }
  2032.     if (!rn2(25)) mon->mcan = 1; /* monster is worn out */
  2033.     if (!tele_restrict(mon)) rloc(mon);
  2034.     return 1;
  2035. }
  2036.  
  2037. static void
  2038. mayberem(obj, str)
  2039. register struct obj *obj;
  2040. const char *str;
  2041. {
  2042.     char qbuf[QBUFSZ];
  2043.  
  2044.     if (!obj || !obj->owornmask) return;
  2045.  
  2046.     if (rn2(20) < ACURR(A_CHA)) {
  2047.         Sprintf(qbuf,"\"Shall I remove your %s, %s?\"",
  2048.             str,
  2049.             (!rn2(2) ? "lover" : !rn2(2) ? "dear" : "sweetheart"));
  2050.         if (yn(qbuf) == 'n') return;
  2051.     } else verbalize("Take off your %s; %s.", str,
  2052.             (obj == uarm)  ? "let's get a little closer" :
  2053.             (obj == uarmc || obj == uarms) ? "it's in the way" :
  2054.             (obj == uarmf) ? "let me rub your feet" :
  2055.             (obj == uarmg) ? "they're too clumsy" :
  2056. #ifdef TOURIST
  2057.             (obj == uarmu) ? "let me massage you" :
  2058. #endif
  2059.             /* obj == uarmh */
  2060.             "let me run my fingers through your hair");
  2061.  
  2062.     if (donning(obj)) cancel_don();
  2063.     if (obj == uarm)  (void) Armor_off();
  2064.     else if (obj == uarmc) (void) Cloak_off();
  2065.     else if (obj == uarmf) (void) Boots_off();
  2066.     else if (obj == uarmg) (void) Gloves_off();
  2067.     else if (obj == uarmh) (void) Helmet_off();
  2068.     else setworn((struct obj *)0, obj->owornmask & W_ARMOR);
  2069. }
  2070. #endif  /* SEDUCE */
  2071.  
  2072. #endif /* OVLB */
  2073.  
  2074. #ifdef POLYSELF
  2075.  
  2076. #ifdef OVL1
  2077.  
  2078. static int
  2079. passiveum(olduasmon,mtmp,mattk)
  2080. struct permonst *olduasmon;
  2081. register struct monst *mtmp;
  2082. register struct attack *mattk;
  2083. {
  2084.     register struct permonst *mdat = mtmp->data;
  2085.     int i, tmp;
  2086.  
  2087.     for(i = 0; ; i++) {
  2088.         if(i >= NATTK) return 1;
  2089.         if(olduasmon->mattk[i].aatyp == AT_NONE) break;
  2090.     }
  2091.     if (olduasmon->mattk[i].damn)
  2092.         tmp = d((int)olduasmon->mattk[i].damn, 
  2093.                                     (int)olduasmon->mattk[i].damd);
  2094.     else if(olduasmon->mattk[i].damd)
  2095.         tmp = d((int)olduasmon->mlevel+1, (int)olduasmon->mattk[i].damd);
  2096.     else
  2097.         tmp = 0;
  2098.  
  2099.     /* These affect the enemy even if you were "killed" (rehumanized) */
  2100.     switch(olduasmon->mattk[i].adtyp) {
  2101.         case AD_ACID:
  2102.         if (!rn2(2)) {
  2103.             pline("%s is splashed by your acid!", Monnam(mtmp));
  2104.             if(resists_acid(mdat)) {
  2105.             pline("%s is not affected.", Monnam(mtmp));
  2106.             tmp = 0;
  2107.             }
  2108.         } else tmp = 0;
  2109.         goto assess_dmg;
  2110.         case AD_STON: /* cockatrice */
  2111.         if (!resists_ston(mdat) &&
  2112. #ifdef MUSE
  2113.             (mattk->aatyp != AT_WEAP || !MON_WEP(mtmp)) &&
  2114. #else
  2115.             (mattk->aatyp != AT_WEAP || !select_hwep(mtmp)) &&
  2116. #endif
  2117.             mattk->aatyp != AT_GAZE && mattk->aatyp != AT_EXPL &&
  2118.             mattk->aatyp != AT_MAGC &&
  2119. #ifdef MUSE
  2120.             (!(mtmp->misc_worn_check & W_ARMG))) {
  2121. #else
  2122.             (!is_mercenary(mdat) ||
  2123.                       !m_carrying(mtmp, LEATHER_GLOVES))) {
  2124. #endif
  2125.             if(poly_when_stoned(mdat)) {
  2126.             mon_to_stone(mtmp);
  2127.             return (1);
  2128.             }
  2129.             pline("%s turns to stone!", Monnam(mtmp));
  2130.             stoned = 1;
  2131.             xkilled(mtmp, 0);
  2132. #ifdef MUSE
  2133.             if (mtmp->mhp > 0) return 1;
  2134. #endif
  2135.             return 2;
  2136.         }
  2137.         return 1;
  2138.         default:
  2139.         break;
  2140.     }
  2141.     if (!u.mtimedone) return 1;
  2142.  
  2143.     /* These affect the enemy only if you are still a monster */
  2144.     if (rn2(3)) switch(uasmon->mattk[i].adtyp) {
  2145.         case AD_PLYS: /* Floating eye */
  2146.         if (tmp > 127) tmp = 127;
  2147.         if (u.umonnum == PM_FLOATING_EYE) {
  2148.             if (!rn2(4)) tmp = 127;
  2149.             if (mtmp->mcansee && haseyes(mtmp->data) && rn2(3) &&
  2150.                 (perceives(mdat) || !Invis)) {
  2151.             if (Blind)
  2152.                 pline("As a blind %s, you cannot defend yourself.",
  2153.                             uasmon->mname);
  2154.                 else {
  2155. #ifdef MUSE
  2156.                 if (mon_reflects(mtmp, 
  2157.                         "Your gaze is reflected by %s %s."))
  2158.                 return 1;
  2159. #endif
  2160.                 pline("%s is frozen by your gaze!", Monnam(mtmp));
  2161.                 mtmp->mcanmove = 0;
  2162.                 mtmp->mfrozen = tmp;
  2163.                 return 3;
  2164.             }
  2165.             }
  2166.         } else { /* gelatinous cube */
  2167.             pline("%s is frozen by you.", Monnam(mtmp));
  2168.             mtmp->mcanmove = 0;
  2169.             mtmp->mfrozen = tmp;
  2170.             return 3;
  2171.         }
  2172.         return 1;
  2173.         case AD_COLD: /* Brown mold or blue jelly */
  2174.         if(resists_cold(mdat)) {
  2175.               shieldeff(mtmp->mx, mtmp->my);
  2176.             pline("%s is mildly chilly.", Monnam(mtmp));
  2177.             golemeffects(mtmp, AD_COLD, tmp);
  2178.             tmp = 0;
  2179.             break;
  2180.         }
  2181.         pline("%s is suddenly very cold!", Monnam(mtmp));
  2182.         u.mh += tmp / 2;
  2183.         if (u.mhmax < u.mh) u.mhmax = u.mh;
  2184.         if (u.mhmax > ((uasmon->mlevel+1) * 8)) {
  2185.             register struct monst *mon;
  2186.  
  2187.             if ((mon = cloneu()) != 0) {
  2188.                 mon->mhpmax = u.mhmax /= 2;
  2189.                 You("multiply from %s heat!", 
  2190.                            s_suffix(mon_nam(mtmp)));
  2191.             }
  2192.         }
  2193.         break;
  2194.         case AD_STUN: /* Yellow mold */
  2195.         if (!mtmp->mstun) {
  2196.             mtmp->mstun = 1;
  2197.             pline("%s staggers.", Monnam(mtmp));
  2198.         }
  2199.         tmp = 0;
  2200.         break;
  2201.         case AD_FIRE: /* Red mold */
  2202.         if(resists_fire(mdat)) {
  2203.               shieldeff(mtmp->mx, mtmp->my);
  2204.             pline("%s is mildly warm.", Monnam(mtmp));
  2205.             golemeffects(mtmp, AD_FIRE, tmp);
  2206.             tmp = 0;
  2207.             break;
  2208.         }
  2209.         pline("%s is suddenly very hot!", Monnam(mtmp));
  2210.         break;
  2211.         case AD_ELEC:
  2212.         if(resists_elec(mdat)) {
  2213.               shieldeff(mtmp->mx, mtmp->my);
  2214.             pline("%s is slightly tingled.", Monnam(mtmp));
  2215.             golemeffects(mtmp, AD_ELEC, tmp);
  2216.             tmp = 0;
  2217.             break;
  2218.         }
  2219.         pline("%s is jolted with your electricity!", Monnam(mtmp));
  2220.         break;
  2221.         default: tmp = 0;
  2222.         break;
  2223.     }
  2224.     else tmp = 0;
  2225.  
  2226.     assess_dmg:
  2227.     if((mtmp->mhp -= tmp) <= 0) {
  2228.         pline("%s dies!", Monnam(mtmp));
  2229.         xkilled(mtmp,0);
  2230. #ifdef MUSE
  2231.         if (mtmp->mhp > 0) return 1;
  2232. #endif
  2233.         return 2;
  2234.     }
  2235.     return 1;
  2236. }
  2237.  
  2238. #endif /* OVL1 */
  2239. #ifdef OVLB
  2240.  
  2241. #include "edog.h"
  2242. struct monst *
  2243. cloneu()
  2244. {
  2245.     register struct monst *mon;
  2246.  
  2247.     if (u.mh <= 1) return(struct monst *)0;
  2248.     if (uasmon->geno & G_EXTINCT) return(struct monst *)0;
  2249.     uasmon->pxlth += sizeof(struct edog);
  2250.     mon = makemon(uasmon, u.ux, u.uy);
  2251.     uasmon->pxlth -= sizeof(struct edog);
  2252.     mon = christen_monst(mon, plname);
  2253.     initedog(mon);
  2254.     mon->m_lev = uasmon->mlevel;
  2255.     mon->mhp = u.mh /= 2;
  2256.     mon->mhpmax = u.mhmax;
  2257.     return(mon);
  2258. }
  2259.  
  2260. #endif /* OVLB */
  2261.  
  2262. #endif /* POLYSELF */
  2263.  
  2264. /*mhitu.c*/
  2265.